using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Security.DataLayer;
using Security.Domain;
using Security.Specs.Common;
using Security.Specs.DataLayer;
using Security.Specs.Services;
using Security.Helpers;
using Security.Specs.Implementation.Common;

namespace Security.Specs.Implementation.Services
{
    [Export(typeof(IDepartmentService))]
    internal class DepartmentService : IDepartmentService
    {
        private readonly ISecurityDataModel model;
        private ValidationService<Department> validationService;

        [ImportingConstructor]
        public DepartmentService(ISecurityDataModel model)
        {
            this.model = model;
            InitializeValidationService();
        }

        public Department New()
        {
            return new Department();
        }

        public ErrorCollection Validate(Department department)
        {
            return validationService.GetErrors(department);
        }

        public string[] IsDepartmentUsedAnywhere(Department department)
        {
            var tables = new List<string>();
            if (model.Employees.Any(e => e.IDDepartment == department.ID))
                tables.Add(Tables.Employees);

            return tables.ToArray();
        }

        private void InitializeValidationService()
        {
            validationService = new ValidationService<Department>();
            validationService.AddRule(d => d.ID.IsEmpty(), StandardErrorReports.IdPropertyNotSet);
            validationService.AddRule(d => string.IsNullOrWhiteSpace(d.Name), StandardErrorReports.NamePropertyNotSet);
            validationService.AddRule(d => model.Departments.Any(dept => dept.ID != d.ID && dept.Name == d.Name), DepartmentWithsameNameAlreadyExists);
        }

        private ErrorReport DepartmentWithsameNameAlreadyExists(Department department)
        {
            return ErrorReport.Create().
                    InObject(department).
                    WithMessage(Strings.DepartmentWithsameNameAlreadyExists(department)).
                    Severity(ErrorSeverity.Warning);
        }
    }
}